package com.leoman.service.impl;

import com.leoman.controller.common.CommonController;
import com.leoman.core.Constant;
import com.leoman.dao.*;
import com.leoman.entity.*;
import com.leoman.entity.vo.CompanyUserAuthVo;
import com.leoman.entity.vo.DataVo;
import com.leoman.entity.vo.StatUserData;
import com.leoman.exception.*;
import com.leoman.service.CompanyUserService;
import com.leoman.utils.DateUtils;
import com.leoman.utils.QiNiuUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartRequest;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;

/**
 * CompanyUserServiceImpl
 * Created by 涂奕恒 on 2016/10/18 0018 下午 3:22.
 */
@Service
public class CompanyUserServiceImpl implements CompanyUserService {

    @Autowired
    private CompanyUserDao companyUserDao;

    @Autowired
    private CompanyAuthDao companyAuthDao;

    @Autowired
    private PersonalAuthDao personalAuthDao;

    @Autowired
    private VideoDao videoDao;

    @Autowired
    private CompanyUserGainDao companyUserGainDao;

    @Override
    public List<CompanyUser> findAll() {
        return companyUserDao.findAll();
    }

    @Override
    public Page<CompanyUser> find(int pageNum, int pageSize) {
        return companyUserDao.findAll(new PageRequest(pageNum - 1, pageSize, Sort.Direction.DESC, "id"));
    }

    @Override
    public Page<CompanyUser> find(int pageNum) {
        return find(pageNum, Constant.PAGE_DEF_SIZE);
    }

    @Override
    public CompanyUser getById(int id) {
        return companyUserDao.findOne(id);
    }

    @Override
    public void deleteById(int id) {
        companyUserDao.delete(id);
    }

    @Override
    public CompanyUser create(CompanyUser companyUser) {
        return companyUserDao.save(companyUser);
    }

    @Override
    public CompanyUser update(CompanyUser companyUser) {
        return companyUserDao.save(companyUser);
    }

    @Override
    @Transactional
    public void deleteAll(int[] ids) {
        for (int id : ids) {
            deleteById(id);
        }
    }

    @Override
    public CompanyUser iFindOneByInfo(Integer companyUserId) throws ParamErrorException, UserNotFindException, UserSealStatusException {
        return AppUserServiceImpl.getCompanyUserInfo(companyUserId, companyUserDao);
    }

    @Override
    public CompanyUserAuthVo iFindInfoByCompanyUserId(Integer companyUserId) throws ParamErrorException, UserNotFindException, UserSealStatusException, NoDataException {
        CompanyUserAuthVo companyUserAuthVo = new CompanyUserAuthVo();
        CompanyUser companyUser = AppUserServiceImpl.getCompanyUserInfo(companyUserId, companyUserDao);

        CompanyAuth companyAuth = null;
        PersonalAuth personalAuth = null;

        if (companyUser.getType().equals(Constant.COMPANY_USER_TYPE_COMPANY)) {
            // 企业用户
            companyAuth = companyAuthDao.findOneByCompanyUserId(companyUserId);
        } else {
            // 个人用户
            personalAuth = personalAuthDao.findOneByCompanyUserId(companyUserId);
        }

        if (null == companyAuth && null == personalAuth) {
            throw new NoDataException();
        }

        if (null != companyAuth) {
            companyUserAuthVo.setName(companyAuth.getCompanyName());
            companyUserAuthVo.setLicenseNum(companyAuth.getLicenseNum());
            companyUserAuthVo.setLicenseUrl1(companyAuth.getLicenseUrl());
            companyUserAuthVo.setLicenseUrl2(companyAuth.getLicenseUrl2());
            companyUserAuthVo.setLicenseUrl3(companyAuth.getLicenseUrl3());
            companyUserAuthVo.setUserName(companyAuth.getUserName());
            companyUserAuthVo.setMobile(companyAuth.getMobile());
            companyUserAuthVo.setType(Constant.COMPANY_USER_TYPE_COMPANY);
        } else {
            companyUserAuthVo.setName(personalAuth.getUserName());
            companyUserAuthVo.setPaperType(personalAuth.getPaperType());
            companyUserAuthVo.setPaperNum(personalAuth.getPaperNum());
            companyUserAuthVo.setUserPaperUrl(personalAuth.getUserPaperUrl());
            companyUserAuthVo.setMobile(personalAuth.getMobile());
            companyUserAuthVo.setEmail(personalAuth.getEmail());
            companyUserAuthVo.setAddress(personalAuth.getAddress());
            companyUserAuthVo.setType(Constant.COMPANY_USER_TYPE_PERSONAL);
        }

        return companyUserAuthVo;
    }

    @Override
    @Transactional
    public void iSaveCompanyAuthInfo(Integer companyUserId, CompanyUserAuthVo companyUserAuthVo, MultipartRequest multipartRequest)
            throws ParamErrorException, UserNotFindException, UserSealStatusException, AuthDataExistException {
        CompanyUser companyUser = AppUserServiceImpl.getCompanyUserInfo(companyUserId, companyUserDao);
        MultipartFile userPaperUrl = multipartRequest.getFile("basePicUrl");

        if (!companyUser.getType().equals(Constant.CHECK_STATUS_DEFAULT) && companyUser.getCheckStatus().equals(Constant.CHECK_STATUS_SUCCESS)) {
            throw new AuthDataExistException();
        }

        if (null == companyUserAuthVo.getType()
                || StringUtils.isBlank(companyUserAuthVo.getName())
                || StringUtils.isBlank(companyUserAuthVo.getMobile())) {
            throw new ParamErrorException();
        }

        if (companyUserAuthVo.getType().equals(Constant.COMPANY_USER_TYPE_COMPANY)) {
            MultipartFile licenseUrl1 = multipartRequest.getFile("url1");
            MultipartFile licenseUrl2 = multipartRequest.getFile("url2");
            MultipartFile licenseUrl3 = multipartRequest.getFile("url3");

            CompanyAuth companyAuth = companyAuthDao.findOneByCompanyUserId(companyUserId);
            if (null == companyAuth) {
                companyAuth = new CompanyAuth();
            }
            companyAuth.setCompanyUser(companyUser);
            companyAuth.setCompanyName(companyUserAuthVo.getName());
            companyAuth.setLicenseNum(companyUserAuthVo.getLicenseNum());

            // 上传图片
            if (null != licenseUrl1 && licenseUrl1.getSize() > 0) {
                if (null != companyAuth.getId()) {
                    QiNiuUtils.delete(companyAuth.getLicenseUrl());
                }
                companyAuth.setLicenseUrl(QiNiuUtils.upload(licenseUrl1));
            }
            if (null != licenseUrl2 && licenseUrl2.getSize() > 0) {
                if (null != companyAuth.getId()) {
                    QiNiuUtils.delete(companyAuth.getLicenseUrl2());
                }
                companyAuth.setLicenseUrl2(QiNiuUtils.upload(licenseUrl2));
            }
            if (null != licenseUrl3 && licenseUrl3.getSize() > 0) {
                if (null != companyAuth.getId()) {
                    QiNiuUtils.delete(companyAuth.getLicenseUrl3());
                }
                companyAuth.setLicenseUrl3(QiNiuUtils.upload(licenseUrl3));
            }

            companyAuth.setUserName(companyUserAuthVo.getUserName());
            companyAuth.setMobile(companyUserAuthVo.getMobile());

            companyAuthDao.save(companyAuth);
        } else {
            PersonalAuth personalAuth = personalAuthDao.findOneByCompanyUserId(companyUserId);
            if (null == personalAuth) {
                personalAuth = new PersonalAuth();
            }
            personalAuth.setCompanyUser(companyUser);
            personalAuth.setUserName(companyUserAuthVo.getName());
            personalAuth.setPaperType(companyUserAuthVo.getPaperType());
            personalAuth.setPaperNum(companyUserAuthVo.getPaperNum());

            if (null != personalAuth.getId()) {
                QiNiuUtils.delete(personalAuth.getUserPaperUrl());
            }
            if (null != userPaperUrl && userPaperUrl.getSize() > 0) {
                QiNiuUtils.delete(personalAuth.getUserPaperUrl());
                personalAuth.setUserPaperUrl(QiNiuUtils.upload(userPaperUrl));
            }
            personalAuth.setMobile(companyUserAuthVo.getMobile());
            personalAuth.setEmail(companyUserAuthVo.getEmail());
            personalAuth.setAddress(companyUserAuthVo.getAddress());

            personalAuthDao.save(personalAuth);
        }

        companyUser.setType(companyUserAuthVo.getType());
        companyUser.setSendTime(System.currentTimeMillis());
        companyUser.setCheckStatus(Constant.CHECK_STATUS_DEFAULT);
        companyUser.setCheckFailReason("");

        companyUserDao.save(companyUser);
    }

    @Override
    public Integer findCountWithNewCompanyUser(Integer index) {
        return companyUserDao.findListByCreateTime(CommonController.getFirstTime(index)).size();
    }

    @Override
    public Integer findCountWithNewCompanyUserNoCheck(Integer index) {
        return companyUserDao.findListNoCheckByCreateTime(CommonController.getFirstTime(index)).size();
    }

    @Override
    public Page<CompanyUser> pageByParams(final String mobile,
                                          final String nickName,
                                          final Integer type,
                                          final Integer status,
                                          Integer sortType,
                                          final Integer isCheck,
                                          final Integer checkStatus,
                                          Integer pageNum,
                                          Integer pageSize) {
        Pageable pageable = new PageRequest(pageNum - 1, pageSize, Sort.Direction.DESC, "id");

        if (null != sortType) {
            if (sortType == 1) {
                // 余额最多
                pageable = new PageRequest(pageNum - 1, pageSize, Sort.Direction.DESC, "money");
            } else {
                // 余额最少
                pageable = new PageRequest(pageNum - 1, pageSize, Sort.Direction.ASC, "money");
            }
        }

        return companyUserDao.findAll(new Specification<CompanyUser>() {
            @SuppressWarnings("ToArrayCallWithZeroLengthArrayArgument")
            @Override
            public Predicate toPredicate(Root<CompanyUser> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                Predicate result = null;
                List<Predicate> predicateList = new ArrayList<>();
                if (StringUtils.isNotBlank(mobile)) {
                    Predicate pre = cb.like(root.get("mobile").as(String.class), "%" + mobile + "%");
                    predicateList.add(pre);
                }
                if (StringUtils.isNotBlank(nickName)) {
                    Predicate pre = cb.like(root.get("nickName").as(String.class), "%" + nickName + "%");
                    predicateList.add(pre);
                }
                if (null == isCheck || isCheck == 0) {
                    if (null != type) {
                        Predicate pre = cb.equal(root.get("type").as(Integer.class), type);
                        predicateList.add(pre);
                    }
                } else {
                    Predicate pre = cb.notEqual(root.get("type").as(Integer.class), Constant.CHECK_STATUS_DEFAULT);
                    predicateList.add(pre);
                    if (null != type) {
                        Predicate pre1 = cb.equal(root.get("type").as(Integer.class), type);
                        predicateList.add(pre1);
                    }
                }
                if (null != checkStatus) {
                    Predicate pre = cb.equal(root.get("checkStatus").as(Integer.class), checkStatus);
                    predicateList.add(pre);
                }
                if (null != status) {
                    Predicate pre = cb.equal(root.get("sealStatus").as(Integer.class), status);
                    predicateList.add(pre);
                }
                if (predicateList.size() > 0) {
                    result = cb.and(predicateList.toArray(new Predicate[]{}));
                }

                if (result != null) {
                    query.where(result);
                }
                return query.getGroupRestriction();
            }

        }, pageable);
    }

    @Override
    public Integer changeCompanyUserStatus(Integer[] companyUserIds, Integer status) {
        try {
            CompanyUser companyUser;
            for (Integer companyUserId : companyUserIds) {
                companyUser = companyUserDao.findOne(companyUserId);
                companyUser.setSealStatus(status);

                companyUserDao.save(companyUser);
            }
            return 1;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    @Override
    public Integer changeCompanyUserCheckStatus(Integer[] companyUserIds, Integer status, String failReasonContent) {
        try {
            CompanyUser companyUser;
            for (Integer companyUserId : companyUserIds) {
                companyUser = companyUserDao.findOne(companyUserId);

                if (companyUser.getCheckStatus().equals(Constant.CHECK_STATUS_DEFAULT)) {
                    companyUser.setCheckStatus(status);
                    companyUser.setNickName(getCompanyUserName(companyUser));
                    companyUser.setCheckFailReason(failReasonContent);

                    companyUserDao.save(companyUser);
                }
            }
            return 1;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    private String getCompanyUserName(CompanyUser companyUser) {
        if (companyUser.getType().equals(Constant.COMPANY_USER_TYPE_PERSONAL)) {
            // 个人
            return personalAuthDao.findOneByCompanyUserId(companyUser.getId()).getUserName();
        } else {
            // 企业
            return companyAuthDao.findOneByCompanyUserId(companyUser.getId()).getCompanyName();
        }
    }

    @Override
    public CompanyUser getInfoByMobile(String mobile) {
        return companyUserDao.findOneByMobile(mobile);
    }

    @Override
    public StatUserData getStatInfoByCompanyUserId(Integer companyUserId) {
        StatUserData statUserData = new StatUserData();
        DataVo dataVo;

        // 查询待审核的视频
        List<Video> waitCheckVideo = videoDao.findListByCompanyUserIdAndCheckStatus(companyUserId, Constant.CHECK_STATUS_DEFAULT);

        // 查询投放中的视频
        List<Video> workingCheckVideo = videoDao.findListByCompanyUserIdAndRecordStatus(companyUserId, Constant.CHECK_STATUS_SUCCESS);

        // 查询未投放的视频
        List<Video> noWorkCheckVideo = videoDao.findListByCompanyUserIdAndRecordStatus(companyUserId, Constant.CHECK_STATUS_DEFAULT);

        // 查询一般形式的视频
        List<Video> defaultVideo = videoDao.findListByCompanyUserIdAndSendType(companyUserId, Constant.VIDEO_SEND_TYPE_DEFAULT);

        // 查询红包形式的视频
        List<Video> moneyVideo = videoDao.findListByCompanyUserIdAndSendType(companyUserId, Constant.VIDEO_SEND_TYPE_MONEY);

        // 查询其他形式的视频
        List<Video> otherVideo = videoDao.findListByCompanyUserIdAndSendType(companyUserId, Constant.VIDEO_SEND_TYPE_OTHER);

        // 计算待审核视频的数量比例
        dataVo = new DataVo();
        dataVo.setName("待审核（" + waitCheckVideo.size() + "）");
        dataVo.setCount(Double.parseDouble(waitCheckVideo.size() + ""));
        statUserData.getClickList().add(dataVo);

        dataVo = new DataVo();
        dataVo.setName("投放中（" + workingCheckVideo.size() + "）");
        dataVo.setCount(Double.parseDouble(workingCheckVideo.size() + ""));
        statUserData.getClickList().add(dataVo);

        dataVo = new DataVo();
        dataVo.setName("未投放（" + noWorkCheckVideo.size() + "）");
        dataVo.setCount(Double.parseDouble(noWorkCheckVideo.size() + ""));
        statUserData.getClickList().add(dataVo);

        // 计算每个类型的视频数量比例
        dataVo = new DataVo();
        dataVo.setName("一般形式（" + defaultVideo.size() + "）");
        dataVo.setCount(Double.parseDouble(defaultVideo.size() + ""));
        statUserData.getMoneyList().add(dataVo);

        dataVo = new DataVo();
        dataVo.setName("红包形式（" + moneyVideo.size() + "）");
        dataVo.setCount(Double.parseDouble(moneyVideo.size() + ""));
        statUserData.getMoneyList().add(dataVo);

        dataVo = new DataVo();
        dataVo.setName("其他形式（" + otherVideo.size() + "）");
        dataVo.setCount(Double.parseDouble(otherVideo.size() + ""));
        statUserData.getMoneyList().add(dataVo);

        return statUserData;
    }

    @Override
    @Transactional
    public Integer savePersonalAuthInfo(CompanyUser companyUser,
                                        String userName,
                                        Integer paperType,
                                        String paperNum,
                                        String mobile,
                                        String email,
                                        String address,
                                        MultipartRequest multipartRequest) {
        try {
            MultipartFile userPaperUrl = multipartRequest.getFile("userPaperUrl");

            PersonalAuth personalAuth = personalAuthDao.findOneByCompanyUserId(companyUser.getId());

            if (null == personalAuth) {
                personalAuth = new PersonalAuth();
                personalAuth.setCompanyUser(companyUser);
            }

            personalAuth.setUserName(userName);
            personalAuth.setPaperType(paperType);
            personalAuth.setPaperNum(paperNum);

            if (null != userPaperUrl && userPaperUrl.getSize() > 0) {
                personalAuth.setUserPaperUrl(QiNiuUtils.upload(userPaperUrl));
            }

            personalAuth.setMobile(mobile);
            personalAuth.setEmail(email);
            personalAuth.setAddress(address);

            personalAuthDao.save(personalAuth);

            companyUser.setType(Constant.COMPANY_USER_TYPE_PERSONAL);
            companyUser.setCheckStatus(Constant.CHECK_STATUS_DEFAULT);
            companyUser.setCheckFailReason(null);
            companyUser.setSendTime(System.currentTimeMillis());

            companyUserDao.save(companyUser);

            return 1;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    @Override
    public Integer saveCompanyAuthInfo(CompanyUser companyUser,
                                       String companyName,
                                       String licenseNum,
                                       String userName,
                                       String mobile,
                                       MultipartRequest multipartRequest) {
        try {
            MultipartFile license_url = multipartRequest.getFile("license_url");
            MultipartFile license_url2 = multipartRequest.getFile("license_url2");
            MultipartFile license_url3 = multipartRequest.getFile("license_url3");

            CompanyAuth companyAuth = companyAuthDao.findOneByCompanyUserId(companyUser.getId());

            if (null == companyAuth) {
                companyAuth = new CompanyAuth();
                companyAuth.setCompanyUser(companyUser);
            }

            companyAuth.setCompanyName(companyName);
            companyAuth.setLicenseNum(licenseNum);

            if (null != license_url && license_url.getSize() > 0) {
                QiNiuUtils.delete(companyAuth.getLicenseUrl());
                companyAuth.setLicenseUrl(QiNiuUtils.upload(license_url));
            }

            if (null != license_url2 && license_url2.getSize() > 0) {
                QiNiuUtils.delete(companyAuth.getLicenseUrl2());
                companyAuth.setLicenseUrl2(QiNiuUtils.upload(license_url2));
            }

            if (null != license_url3 && license_url3.getSize() > 0) {
                QiNiuUtils.delete(companyAuth.getLicenseUrl3());
                companyAuth.setLicenseUrl3(QiNiuUtils.upload(license_url3));
            }

            companyAuth.setUserName(userName);
            companyAuth.setMobile(mobile);

            companyAuthDao.save(companyAuth);

            companyUser.setType(Constant.COMPANY_USER_TYPE_COMPANY);
            companyUser.setCheckStatus(Constant.CHECK_STATUS_DEFAULT);
            companyUser.setCheckFailReason(null);
            companyUser.setSendTime(System.currentTimeMillis());

            companyUserDao.save(companyUser);

            return 1;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    @Override
    public Double statTodayMoney(CompanyUser companyUser) {
        try {
            // 获取今日初始时间戳
            Long startTime = DateUtils.stringToDateWithFormat(DateUtils.longToStringWithFormat(System.currentTimeMillis(), "yyyy-MM-dd") + " 00:00:00", "yyyy-MM-dd hh:mm:ss").getTime();
            // 获取今日结束时间戳
            Long endTime = DateUtils.stringToDateWithFormat(DateUtils.longToStringWithFormat(System.currentTimeMillis(), "yyyy-MM-dd") + " 23:59:59", "yyyy-MM-dd hh:mm:ss").getTime();

            Double todayMoney = 0.0;
            List<CompanyUserGain> list = companyUserGainDao.findListByParams(companyUser.getId(), startTime, endTime, "%投放视频%");

            for (CompanyUserGain companyUserGain : list) {
                todayMoney += companyUserGain.getMoney();
            }

            return todayMoney;
        } catch (Exception e) {
            e.printStackTrace();
            return 0.0;
        }
    }

    @Override
    @Transactional
    public Integer changeCompanyUserMoney(Integer companyUserId, Double money) {
        try {
            CompanyUser companyUser = companyUserDao.findOne(companyUserId);

            // 记录原先账户余额
            Double oldMoney = companyUser.getMoney();

            // 比对变动金额
            Double changeMoney = money - oldMoney;

            // 记录金额变动记录
            CompanyUserGain companyUserGain = new CompanyUserGain();
            companyUserGain.setCompanyUser(companyUser);
            companyUserGain.setContent("网站管理员操作");
            companyUserGain.setMoney(changeMoney);

            companyUserGainDao.save(companyUserGain);

            // 修改企业用户账户余额
            companyUser.setMoney(money);
            companyUserDao.save(companyUser);

            return 1;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }
}